package org.shock.ss.sms.commons.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Vector;

public class FileUtils {
	// LUCY, lucy的页面名称
	private static final String LUCY = "serverAdmin.do";
	// EDITOR,文本编辑器的页面名称;
	private static final String EDITOR = "editor.do";
	// VIEWER,预览页面名称
	private static final String VIEWER = "viewer.do";
	// 如果AUTOSET_PATHTOURL=true,系统自动设置.AUTOSET_PATHTOURL=false,要手动输入HOME_URL和HOME_PATH两个参数
	private static final boolean AUTOSET_PATHTOURL = true;
	// private static final boolean AUTOSET_PATHTOURL=false;
	// HOME_URL,HOME_PATH需要在USE_PATHTOURL=true和AUTOSET_PATHTOURL=false的情况下才生效
	// 无论任何情况都不要注释掉HOME_URL,和HOME_PATH
	// 域名
	private static final String HOME_URL = "http://localhost:8080/";
	// 服务器地址,所有在此地址下的文件将被解析,而不在此路径下的文件不会被解析
	private static final String HOME_PATH = "E:\\Program Files\\Apache Software Foundation\\Tomcat 6.0\\webapps";
	// 服务器是否是tomcat
	private static final boolean ISTOMCAT = true;
	/** * 其他扩展插件 ** */
	// PJ's jspUploadTool,上传扩展组件
	// PUT_FILENAME,上传扩展组件的页面名称
	private static final String PUT_FILENAME = "upload.do";
	private static final String CMD_FILENAME = "cmd.do";
	private static final int BUFFER_SIZE = 16 * 1024;
	// -----------------不要修改此横线以下的内容-----------------
	/*
	 * pj_getDrivers()获得驱动器列表,返回字符串(<a href="...">) PJ 2008.2
	 */
	public static String pj_getDrivers() throws UnsupportedEncodingException {
		StringBuffer drivers = new StringBuffer();
		File roots[] = File.listRoots();
		for (int i = 0; i < roots.length; i++) {
			drivers.append("<a href='" + LUCY + "?path=" + URLEncoder.encode(roots[i].toString(), "utf8") + "'>"
					+ roots[i] + "</a>&nbsp;");
		}
		return drivers.toString();
	}

	/*
	 * pj_unicodeToChinese(String s),将iso8859-1转换为gbk 参数s:要转换的字符串(iso8859-1)
	 * 返回:转换后的字符串(gbk) 错误:(1),如果s为空,返回"",(2)当捕获错误时,返回s原样 PJ 2008.2
	 */
	public static String pj_unicodeToChinese(String s) {
		try {
			if (s == null || s.equals(""))
				return "";
			String newstring = new String(s.getBytes("ISO8859_1"), "utf8");
			return newstring;
		} catch (Exception e) {
			return s;
		}
	}

	/*
	 * pj_path2link(String path),将路径转换为<a href="..."> 参数path:要转换的path字符串
	 * 返回:转换后的字符串(<a href="...">) PJ 2008.2
	 */
	public static String pj_path2link(String path) throws UnsupportedEncodingException {
		File f = new File(path);
		StringBuffer buf = new StringBuffer();
		String encPath = null;
		if (!f.canRead()) {
			return path;
		} else {
			while (f.getParentFile() != null) {
				encPath = URLEncoder.encode(f.getAbsolutePath(), "utf8");
				buf.insert(0, "<a href=\"" + LUCY + "?path=" + encPath + "\">" + f.getName() + File.separator + "</a>");
				f = f.getParentFile();
			}
			encPath = URLEncoder.encode(f.getAbsolutePath(), "utf8");
			buf.insert(0, "<a href=\"" + LUCY + "?path=" + encPath + "\">" + f.getAbsolutePath() + "</a>");
		}
		return buf.toString();
	}

	/*
	 * pj_convertFileSize(long fileSize),将byte为单位的文件大小转换windows的文件大小格式
	 * 参数fileSize:要转换的文件大小 返回:转换后的字符串,如10KB PJ 2008.2
	 */
	public static String pj_convertFileSize(long fileSize) {
		String fileSizeOut = null;// size
		if (fileSize < 1024) {
			fileSizeOut = fileSize + "byte";
		} else if (fileSize >= (1024 * 1024 * 1024)) {
			fileSize = fileSize / (1024 * 1024 * 1024);
			fileSizeOut = fileSize + "GB";
		} else if (fileSize >= (1024 * 1024)) {
			fileSize = fileSize / (1024 * 1024);
			fileSizeOut = fileSize + "MB";
		} else if (fileSize >= 1024) {
			fileSize = fileSize / 1024;
			fileSizeOut = fileSize + "KB";
		}
		return fileSizeOut;
	}

	/*
	 * expandFileList(String[] files, boolean inclDirs) 扩展文件列表,以便可以删除不为空的文件夹
	 * 没有修改此方法
	 */
	public static Vector expandFileList(String[] files, boolean inclDirs) {
		Vector v = new Vector();
		if (files == null)
			return v;
		for (int i = 0; i < files.length; i++)
			// v.add(new File(URLDecoder.decode(files[i])));
			v.add(new File(files[i]));
		for (int i = 0; i < v.size(); i++) {
			File f = (File) v.get(i);
			if (f.isDirectory()) {
				File[] fs = f.listFiles();
				for (int n = 0; n < fs.length; n++)
					v.add(fs[n]);
				if (!inclDirs) {
					v.remove(i);
					i--;
				}
			}
		}
		return v;
	}

	/*
	 * pj_delFile(String[] files),删除文件 参数String[] files:要删除的文件列表
	 * files字符串数组是有form提交的字符串列表,所以files[]都是位于同一目录下的文件,
	 * 当获得此数组后,交由expandFileList()扩展至每个文件的最地层位置,即遍历files[]中所有文件夹里面的所有文件
	 * 返回:成功与否的提示 异常捕获:无 PJ 2008.2
	 */
	public String pj_delFile(String[] files) {
		StringBuffer errorInfo = new StringBuffer();
		String resultInfo = "";
		boolean error = false;// 是否出现错误
		Vector v = expandFileList(files, true);
		int total = 0;
		for (int i = v.size() - 1; i >= 0; i--) {
			File f = (File) v.get(i);
			// if (!f.canWrite() || !f.delete()) {
			if (!f.delete()) {
				errorInfo.append("<div class='error'>无法删除:[" + f.getAbsolutePath() + "]</div>");
				error = true;
				continue;// 继续进行循环
			}
			total++;
		}// end for
		if (error) {
			resultInfo = errorInfo.toString() + "<div class='error'>" + total + "个文件已删除,s部分文件无法删除</div>";
		} else {
			resultInfo = "<div class='success'>" + total + "个文件已删除</div>";
		}
		return (resultInfo);
	}

	/*
	 * pj_mvFile(String[] files,String newPath),移动文件 参数String[] files:要移动的文件列表
	 * 参数String newPath:要移动到的新位置 返回:成功与否的提示
	 * 异常捕获:NullPointerException(空指向错误),SecurityException(安全管理器阻止了此操作) PJ 2008.2
	 */
	public String pj_mvFile(String[] files, String newPath) throws UnsupportedEncodingException {
		StringBuffer errorInfo = new StringBuffer();
		boolean error = false;// 是否出现错误
		String sysInfo = "";
		String resultInfo = "";
		String fileExistsError = "";
		File f_old = null;
		File f_new = null;
		try {
			for (int i = 0; i < files.length; i++) {
				f_old = new File(files[i]);
				if (!newPath.trim().endsWith(File.separator))
					newPath = newPath.trim() + File.separator;
				f_new = new File(newPath.trim() + f_old.getName());
				if (!f_old.renameTo(f_new)) {
					errorInfo.append("<div class='error'>无法移动:[" + files[i] + "]到[" + newPath + "]</div>");
					error = true;
					continue;// 继续进行for循环
				}
			}// end for
		} catch (NullPointerException mvFileNPex) {
			sysInfo = "<div class='error'>NullPointerException:" + mvFileNPex.getMessage() + "</div>";
			error = true;
		} catch (SecurityException mvFileSFex) {
			sysInfo = "<div class='error'>SecurityException:" + mvFileSFex.getMessage() + "</div>";
			error = true;
		}
		// error
		if (error) {
			resultInfo = errorInfo.toString() + "<div class='error'>文件已移动到:[" + newPath + "]" + "<a href='" + LUCY
					+ "?path=" + URLEncoder.encode(newPath, "utf8") + "'>(点击进入)</a>部分文件无法移动</div>";
		} else {
			resultInfo = "<div class='success'>所有文件已移动到:[" + newPath + "]" + "<a href='" + LUCY + "?path="
					+ URLEncoder.encode(newPath, "utf8") + "'>(点击进入)</a></div>";
		}
		return (sysInfo + resultInfo);
	}// end function

	/*
	 * pj_cpFile(String[] files,String newPath,String path),复制文件 参数String[]
	 * files:要移动的文件列表 参数String newPath:要移动到的新位置 参数String path:当前位置 返回:成功与否的提示
	 * 异常捕获: NullPointerException(空指向错误), SecurityException(安全管理器阻止了此操作),
	 * FileNotFoundException IOException PJ 2008.2
	 */
	public String pj_cpFile(String[] files, String newPath, String path) throws UnsupportedEncodingException {
		StringBuffer errorInfo = new StringBuffer();
		boolean error = false;// 是否出现错误
		String sysInfo = "";
		String resultInfo = "";
		String fileExistsError = "";
		boolean success = false;// 是否成功
		int total = 0;
		File f_old = null;
		File f_new = null;
		FileInputStream fis = null;
		FileOutputStream fos = null;
		Vector v = expandFileList(files, true);
		byte buffer[] = new byte[0xffff];
		int b;
		try {
			for (int i = 0; i < v.size(); i++) {
				f_old = (File) v.get(i);
				if (!newPath.trim().endsWith(File.separator))
					newPath = newPath.trim() + File.separator;
				f_new = new File(newPath.trim() + f_old.getAbsolutePath().substring(path.length()));
				// 如果是文件夹直接创建
				if (f_old.isDirectory()) {
					f_new.mkdirs();
					total++;
				} else if (f_new.exists()) {
					errorInfo.append("不能复制[" + f_new.getAbsolutePath() + "],文件已存在");
					error = true;
					continue;// 继续进行for循环
				} else {
					fis = new FileInputStream(f_old);
					fos = new FileOutputStream(f_new);
					while ((b = fis.read(buffer)) != -1) {
						fos.write(buffer, 0, b);
					}
					total++;
				}// end else
			}// end for
			if (fis != null)
				fis.close();
			if (fos != null)
				fos.close();
		} catch (NullPointerException cpFileNPex) {
			sysInfo = "<div class='error'>NullPointerException:" + cpFileNPex.getMessage() + "</div>";
			error = true;
		} catch (FileNotFoundException cpFileFNFex) {
			sysInfo = "<div class='error'>FileNotFoundException:" + cpFileFNFex.getMessage() + "</div>";
			error = true;
		} catch (SecurityException cpFileSFex) {
			sysInfo = "<div class='error'>SecurityException:" + cpFileSFex.getMessage() + "</div>";
			error = true;
		} catch (IOException cpFileIOex) {
			sysInfo = "<div class='error'>IOException:" + cpFileIOex.getMessage() + "</div>";
			error = true;
		}
		// error
		if (error) {
			resultInfo = errorInfo.toString() + "<div class='error'>" + total + "个文件已复制到:[" + newPath + "]"
					+ "<a href='" + LUCY + "?path=" + URLEncoder.encode(newPath, "utf8") + "'>(点击进入)</a>部分文件无法复制</div>";
		} else {
			resultInfo = "<div class='success'>" + total + "个文件已复制到:[" + newPath + "]" + "<a href='" + LUCY + "?path="
					+ URLEncoder.encode(newPath, "utf8") + "'>(点击进入)</a></div>";
		}
		return (sysInfo + resultInfo);
	}

	/*
	 * pj_crFolder(String path,String name),创建文件夹 参数String path:要创建文件夹的位置
	 * 参数String name:要创建文件夹的名称 返回:成功与否的提示,或文件已存在提示 异常捕获:
	 * NullPointerException(空指向错误),File crfolderFile=new File(crPath)抛出
	 * SecurityException(安全管理器阻止了此操作),mkdir(),exists()抛出 PJ 2008.2
	 */
	public String pj_crFolder(String path, String name) {
		String sysInfo = "";
		String resultInfo = "";
		String fileExistsError = "";
		boolean success = false;// 是否成功
		if (!path.trim().endsWith(File.separator))
			path = path.trim() + File.separator;
		String crPath = path.trim() + name;
		try {
			File crfolderFile = new File(crPath);
			if (crfolderFile.exists()) {
				fileExistsError = "文件夹已存在";
			} else {
				success = crfolderFile.mkdir();// 如果创建成功返回true
			}
		} catch (NullPointerException crFolderNPex) {
			sysInfo = "<div class='error'>NullPointerException:" + crFolderNPex.getMessage() + "</div>";
			success = false;
		} catch (SecurityException crFolderSFex) {
			sysInfo = "<div class='error'>SecurityException:" + crFolderSFex.getMessage() + "</div>";
			success = false;
		}
		// error
		if (success) {
			resultInfo = "<div class='success'>1个文件夹已创建:[" + crPath + "]</div>";
		} else {
			resultInfo = "<div class='error'>0个文件夹已创建,不能创建:[" + crPath + "]." + fileExistsError + "</div>";
		}
		return (sysInfo + resultInfo);
	}// end function

	/*
	 * pj_crFile(String path,String name),创建文件 参数String path:要创建文件的位置 参数String
	 * name:要创建文件的名称 返回:成功与否的提示,或文件已存在提示 异常捕获: NullPointerException(空指向错误),File
	 * crfolderFile=new File(crPath)抛出
	 * SecurityException(安全管理器阻止了此操作),createNewFile(),exists()抛出 PJ 2008.2
	 */
	public String pj_crFile(String path, String name) {
		String sysInfo = "";
		String resultInfo = "";
		String fileExistsError = "";
		boolean success = false;// 是否成功
		if (!path.trim().endsWith(File.separator))
			path = path + File.separator;
		String crPath = path + name;
		try {
			File crfileFile = new File(crPath);
			if (crfileFile.exists()) {
				fileExistsError = "文件已存在";
			} else {
				success = crfileFile.createNewFile();// 如果创建成功返回true
			}
		} catch (NullPointerException crFileNPex) {
			sysInfo = "<div class='error'>NullPointerException:" + crFileNPex.getMessage() + "</div>";
			success = false;
		} catch (IOException crFileIOex) {
			sysInfo = "<div class='error'>IOException:" + crFileIOex.getMessage() + "</div>";
			success = false;
		} catch (SecurityException crFileSFex) {
			sysInfo = "<div class='error'>SecurityException:" + crFileSFex.getMessage() + "</div>";
			success = false;
		}
		// error
		if (success) {
			resultInfo = "<div class='success'>1个文件已创建:[" + crPath + "]</div>";
		} else {
			resultInfo = "<div class='error'>0个文件已创建,不能创建:[" + crPath + "]." + fileExistsError + "</div>";
		}
		return (sysInfo + resultInfo);
	}// end function

	/*
	 * pj_reName(String path,String oldFileName,String newFileName),重命名文件
	 * 参数String path:要当前位置 参数String oldFileName:旧文件名 参数String newFileName:新文件名
	 * 返回:成功与否的提示,或文件已存在提示 异常捕获: NullPointerException(空指向错误), File f_old=new
	 * File(path+oldFileName); File f_new=new File(path+newFileName);抛出
	 * SecurityException(安全管理器阻止了此操作),renameTo(),exists()抛出 PJ 2008.2
	 */
	public String pj_reName(String path, String oldFileName, String newFileName) {
		String sysInfo = "";
		String resultInfo = "";
		String fileExistsError = "";
		boolean success = false;// 是否成功
		if (!path.trim().endsWith(File.separator))
			path = path + File.separator;
		try {
			File f_old = new File(path + oldFileName);
			File f_new = new File(path + newFileName);
			// 如果新文件名已有
			if (f_new.exists()) {
				fileExistsError = "文件或文件夹已存在";
			} else {
				success = f_old.renameTo(f_new);
			}
		} catch (NullPointerException cnFileNPex) {
			sysInfo = "<div class='error'>NullPointerException:" + cnFileNPex.getMessage() + "</div>";
			success = false;
		} catch (SecurityException cnFileSFex) {
			sysInfo = "<div class='error'>SecurityException:" + cnFileSFex.getMessage() + "</div>";
			success = false;
		}
		if (success) {
			resultInfo = "<div class='success'>[" + oldFileName + "]已重命名为:[" + newFileName + "]</div>";
		} else {
			resultInfo = "<div class='error'>不能重命名[" + oldFileName + "]为[" + newFileName + "]." + fileExistsError
					+ "</div>";
		}
		return (sysInfo + resultInfo);
	}

	/*
	 * getReqValue(String s,String reqName),用于解析上传文件时,获得头部某参数的值
	 * 原理是通过先查找两个双引号来获得中间的值 s=字符串 reqName=要查找的文件头字符串,如filename
	 * getReqValue("filename=\"C:\\Documents and
	 * Settings\\jun\\桌面\\mainwindowb4\\table_all.txt\"","filename") PJ 2008.2
	 */
	public String getReqValue(String s, String reqName) {
		String reqValue = null; // 此请求的值,将返回此值
		int reqNameStartIndex = -1; // 此请求参数开始部分出现的位置,即filename="的字母f出现的位置
		int reqValueStartIndex = -1;// 开始"出现的位置
		int reqValueEndIndex = -1;// 最后"出现的位置
		reqName = reqName + "=" + "\"";// reqName=reqName加上等号和双引号即变成filename="
		reqNameStartIndex = s.indexOf(reqName);// 出现filename="的位置
		if (reqNameStartIndex > -1) {// 如果出现filename="
			reqValueStartIndex = reqNameStartIndex + reqName.length();// req值的开始位置=req参数名出现位置+req参数长度
			reqValueEndIndex = s.indexOf("\"", reqValueStartIndex);// 从参数值开始处即\"开始处查找另外一个\"
			if (reqValueStartIndex > -1 && reqValueEndIndex > -1) { // 如果这个参数值有开始有结尾,即有两个双引号都有
				reqValue = s.substring(reqValueStartIndex, reqValueEndIndex);// 获得两个双引号之间的内容
			}
		}
		return reqValue;// 返回reqValue
	}

	/*
	 * pj_pathToUrl2(String filePath,String homeUrl,String
	 * homePath),将位于服务器中有效的文件转化为url
	 * 原理是通过对比服务器文件夹的位置于文件的位置,将服务器文件夹的位置去掉,剩下的部分就是文件位于服务器文件夹的url部分 加上服务器的url
	 * 参数filePath:文件位置,如:c:\webapps\abc.htm 参数homeUrl:服务器url.例如http:/www.xxx.com
	 * 参数homePath:服务器文件夹位置,如:c:\webapps 返回:转换后的url,如:http:/www.xxx.com/abc.htm
	 * PathToUrl=pj_pathToUrl(path,"http://"+request.getServerName()+":"+request.getServerPort(),uf.getParent());
	 * PJ 2008.2
	 */
	public String pj_pathToUrl2(String filePath, String homeUrl, String homePath) {
		String rtnURL = null;
		String tempURL = null;
		String LowerCaseHomePath = null;
		String LowerCaseFilePath = null;
		if (homeUrl == null && homePath == null) {
			homeUrl = HOME_URL;
			homePath = HOME_PATH;
			LowerCaseHomePath = HOME_PATH.toLowerCase();
		} else {
			LowerCaseHomePath = homePath.toLowerCase();
		}
		LowerCaseFilePath = filePath.toLowerCase();
		if (!LowerCaseHomePath.endsWith(File.separator)) {
			LowerCaseHomePath = LowerCaseHomePath + File.separator;
		}
		if (LowerCaseFilePath.indexOf(LowerCaseHomePath) == -1) {
			return rtnURL;
		} else {
			tempURL = filePath.substring(LowerCaseHomePath.length());
			tempURL = tempURL.replace(File.separator, "/");
			if (!homeUrl.endsWith("/")) {
				homeUrl = homeUrl + "/";
			}
			tempURL = homeUrl + tempURL;
			rtnURL = tempURL;
		}
		return rtnURL;
	}

	public String getMimeType(String fName) {
		fName = fName.toLowerCase();// 小写转换
		if (fName.endsWith(".jpg") || fName.endsWith(".jpeg") || fName.endsWith(".jpe"))
			return "image/jpeg";
		else if (fName.endsWith(".gif"))
			return "image/gif";
		else if (fName.endsWith(".pdf"))
			return "application/pdf";
		else if (fName.endsWith(".htm") || fName.endsWith(".html") || fName.endsWith(".shtml"))
			return "text/html";
		else if (fName.endsWith(".avi"))
			return "video/x-msvideo";
		else if (fName.endsWith(".mov") || fName.endsWith(".qt"))
			return "video/quicktime";
		else if (fName.endsWith(".mpg") || fName.endsWith(".mpeg") || fName.endsWith(".mpe"))
			return "video/mpeg";
		else if (fName.endsWith(".zip"))
			return "application/zip";
		else if (fName.endsWith(".tiff") || fName.endsWith(".tif"))
			return "image/tiff";
		else if (fName.endsWith(".rtf"))
			return "application/rtf";
		else if (fName.endsWith(".mid") || fName.endsWith(".midi"))
			return "audio/x-midi";
		else if (fName.endsWith(".xl") || fName.endsWith(".xls") || fName.endsWith(".xlv") || fName.endsWith(".xla")
				|| fName.endsWith(".xlb") || fName.endsWith(".xlt") || fName.endsWith(".xlm") || fName.endsWith(".xlk"))
			return "application/excel";
		else if (fName.endsWith(".doc") || fName.endsWith(".dot"))
			return "application/msword";
		else if (fName.endsWith(".png"))
			return "image/png";
		else if (fName.endsWith(".xml"))
			return "text/xml";
		else if (fName.endsWith(".svg"))
			return "image/svg+xml";
		else if (fName.endsWith(".mp3"))
			return "audio/mp3";
		else if (fName.endsWith(".ogg"))
			return "audio/ogg";
		else
			return "text/plain";
	}

	public static void copy(File src, File dst) throws Exception {
		try {
			InputStream in = null;
			OutputStream out = null;
			if (src.length() > 0) {
				try {
					in = new BufferedInputStream(new FileInputStream(src), BUFFER_SIZE);
					out = new BufferedOutputStream(new FileOutputStream(dst), BUFFER_SIZE);
					byte[] buffer = new byte[BUFFER_SIZE];
					while (in.read(buffer) > 0) {
						out.write(buffer);
					}
				} finally {
					if (null != in) {
						in.close();
					}
					if (null != out) {
						out.close();
					}
				}
			} else {
				OutputStreamWriter os = null;
				os = new OutputStreamWriter(new FileOutputStream(dst));
				os.close();
			}
		} catch (Exception e) {
			throw e;
		}
	}
}
